#pragma once
#include <iostream>
#include <fstream>
#include <string>
#include <unistd.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>

enum 
{
    UNKNOW = 0,
    DEBUG,
    WARRING,
    ERROR,
    FATAL
};
const std::string log_file = "./log/tcp_server.log";

static bool exists(const std::string &pathname)
{
    // 方法1 获取文件状态，若存在则可能获取成功，若不存在则一定失败
    struct stat st;
    if (stat(pathname.c_str(), &st) < 0)
    {
        return false;
    }
    return true;
    //  方法2 access  是一个系统调用接口，使用后代码移植性不好
    //  return (access(pathname.c_str(), F_OK) == 0);
}
static std::string path(const std::string &pathname)
{
    // ./abc/a.txt
    size_t pos = pathname.find_last_of("/\\");
    if (pos == std::string::npos)
        return ".";
    return pathname.substr(0, pos + 1);
}

static void createDirectory(const std::string &pathname)
{
    // ./abc/a
    size_t pos = 0, idx = 0;
    while (idx < pathname.size())
    {
        pos = pathname.find_first_of("/\\", idx);
        if (pos == std::string::npos)
        {
            mkdir(pathname.c_str(), 0777);
        }

        std::string parent_dir = pathname.substr(0, pos + 1);
        if (!exists(parent_dir.c_str()))
        {
            mkdir(parent_dir.c_str(), 0777);
        }
        idx = pos + 1;
    }
}

std::string toLevelString(int level)
{
    switch (level)
    {
    case UNKNOW:
        return "UNKNOW";
    case DEBUG:
        return "DEBUG";
    case WARRING:
        return "WARRING";
    case ERROR:
        return "ERROR";
    case FATAL:
        return "FATAL";
    default:
        return "UNKNOW";
    }
}
static std::string getTime()
{
    time_t nowtime;
    time(&nowtime);              // 获取1900年1月1日0点0分0秒到现在经过的秒数
    tm *p = localtime(&nowtime); // 将秒数转换为本地时间,年从1900算起,需要+1900,月为0-11,所以要+1
    char buffer[128];
    snprintf(buffer, sizeof(buffer), "%04d:%02d:%02d %02d:%02d:%02d", p->tm_year + 1900, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
    return buffer;
}

// 输出格式 日志等级 时间 pid 内容
static void logMessage(int level, const char *format, ...)
{
    std::string str_level = toLevelString(level);
    std::string str_time = getTime();
    std::string str_pid = std::to_string(getpid());
    char log_left[1024];
    snprintf(log_left, sizeof(log_left), "[%s][%s][%s]", str_level.c_str(), str_time.c_str(), str_pid.c_str());
    char log_right[1024];
    va_list args;           // 定义va_list类型的args变量
    va_start(args, format); // 初始化args指向第一个可选参数
    vsnprintf(log_right, sizeof(log_right), format, args);
    va_end(args); // 结束对可变参数列表的操作
    printf("%s%s\n", log_left, log_right);
    if (!exists(path(log_file))) {
        createDirectory(path(log_file));
    }
    FILE* file = fopen(log_file.c_str(), "a+");
    if (file == nullptr) {
        std::cout << "open file failed" << std::endl;
        return;
    }
    fprintf(file, "%s%s\n", log_left, log_right);
}
